package FollowTest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;

public class Server {

    public static final Logger logger = LoggerFactory.getLogger("Server.class");
    static ArrayList<Socket> list = new ArrayList<>();

    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(10000);

        //1.把本地文件中正确的用户名和密码先获取到
        Properties pro = new Properties();
        FileInputStream fis = new FileInputStream
                ("/Users/lujingxiang/IdeaProjects/" +
                        "ChatRoom/src/FollowTest/" +
                        "UsersInfo.txt");

        pro.load(fis);

        fis.close();

        //2.接收客户端的数据并进行判断，只要来一个客户端就来一条线程
        while(true)
        {
            Socket socket = ss.accept();
            logger.info("有客户端来连接");
            //获取客户端的数据之后，要把正确用户名密码传入
            //开启新一条线程，把任务交给线程去处理
            new Thread(new MyRunnable(socket,pro)).start();
        }

    }
}

class MyRunnable implements Runnable
{
    public static final Logger logger = LoggerFactory.getLogger("MyRunnable.class");
    Socket socket;
    Properties pro;

    public MyRunnable(Socket socket,Properties pro)
    {
        this.pro=pro;
        this.socket=socket;
    }
    @Override
    public void run() {
        try {
            //服务器要相应两次操作
            //第一次读的是操作
            //第二次才是信息
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(socket.getInputStream()));

            while (true) {
                String choose = br.readLine();

                switch (choose)
                {
                    case "login" -> login(br);
                    case "register" -> register(br);

                }
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    public void register(BufferedReader br) throws IOException
    {
        logger.info("用户选择了注册操作");

        String userinfo = br.readLine();

        String userName = userinfo.split("&")[0].
                split("=")[1];
        String password = userinfo.split("&")[1].
                split("=")[1];
        String againPassword = userinfo.split("&")[2].
                split("=")[1];

        //四种情况
        //1.用户名已存在
        //2.密码必须是6-16位，且只包含数字和小写字母
        //3.密码两次输入不一致
        //4.注册成功
        if(!pro.containsKey(userName))
        {
            //用户名不存在，下一步判断
            String rule = "\\S*(?=\\S{6,16})(?=\\S*\\d)(?=\\S*[a-z])\\S*";
            if(password.matches(rule))
            {
                //密码符合规则，下一步判断
                if(password.equals(againPassword))
                {
                    //两次密码输入一致，登录成功
                    writeMessageToClient("4");
                    logger.info("注册成功！用户名："+userName+" 密码："+password);
                    //将用户信息输入到集合中，然后再储存操作
                    pro.put(userName,password);
                    FileOutputStream fos = new FileOutputStream
                            ("/Users/lujingxiang/IdeaProjects/" +
                                    "ChatRoom/src/FollowTest/" +
                                    "UsersInfo.txt");
                    pro.store(fos,null);
                    fos.close();
                }
                else
                {
                    //两次密码输入不一致
                    writeMessageToClient("3");
                }
            }
            else
            {
                //密码不符合规则
                writeMessageToClient("2");
            }
        }
        else
        {
            //已存在，错误
            writeMessageToClient("1");
        }

    }

    public void login(BufferedReader br) throws IOException {
        //获取用户登录时传递过来的信息，并进行判断
        logger.info("用户选择了登录操作");
        String userinfo = br.readLine();
        String userName = userinfo.split("&")[0].
                split("=")[1];
        String password = userinfo.split("&")[1].
                split("=")[1];

        //三种情况：
        //1.
        if(pro.containsKey(userName))
        {
            //如果用户名存在，则继续判断
            String rightPassword = (String) pro.get(userName);
            if(rightPassword.equals(password))
            {
                //提示用户登录成功，可以开始聊天
                writeMessageToClient("1");
                logger.info("登录成功！用户名："+userName+" 密码："+password);
                //登录成功之后，就要逐个把每个客户端的socket对象保存起来
                //用于之后的群发
                Server.list.add(socket);

                //模拟一个while (true),模拟聊天
                //while (true){}
                // 聊天代码
                //接收客户端发送过来的信息并打印在控制台

                //一个方法中一般只能写一个功能，不超过20行代码
                talk2All(br,userName);
            }
            else
            {
                //密码输入错误,重新处理登录请求
                writeMessageToClient("2");
            }
        }
        else
        {
            //不存在，直接回写
            writeMessageToClient("3");
        }
    }

    public void writeMessageToClient(String Message) throws IOException
    {
        //获取输出流
        BufferedWriter bw = new BufferedWriter(new
                OutputStreamWriter(socket.getOutputStream()));

        bw.write(Message);
        bw.newLine();
        bw.flush();
    }

    public void writeMessageToClient(Socket s,String Message) throws IOException
    {
        //获取输出流
        BufferedWriter bw = new BufferedWriter(new
                OutputStreamWriter(s.getOutputStream()));

        bw.write(Message);
        bw.newLine();
        bw.flush();
    }

    public void talk2All(BufferedReader br,String userName) throws IOException
    {
        while (true)
        {
            String message = br.readLine();
            //message = harmonyTalk(message);
            logger.info(userName+"发送消息："+message);
            for (Socket s : Server.list) {
                //s依次表示每一个客户端的连接对象
                writeMessageToClient(s,userName+"发送消息："+message);
            }
        }
    }

    @SuppressWarnings("all")
    private static String harmonyTalk(String message) throws IOException{
        ArrayList<String> list = new ArrayList<>();
        BufferedReader wbr = new BufferedReader(new InputStreamReader
                (new FileInputStream("src/FollowTest/words.data")));
        String str = wbr.readLine();
        wbr.close();
        for (String s : str.split("&")) {
            list.add(s);
        }
        //替换
        for (String s : list) {
            if(message.contains(s))
            {
                int len = s.length();
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < len; i++) {
                    sb.append("*");
                }
                String replacement = sb.toString();
                message = message.replace(s,replacement);
            }
        }
        return message;
    }
}
